//
//  LRTableViewController.swift
//  TodoItemDemo
//
//  Created by lee tank on 2017/7/31.
//  Copyright © 2017年 RoseVision. All rights reserved.
//

import UIKit


class LRTableViewController: UITableViewController {
   
    enum Action: ActionType {
        case updateText(text: String)
        case addTodos(items: [String])
        case removeTodo(index: Int)
        case loadToDos
    }
    
    enum Command: CommandType {
        case loadToDos(completion:([String]) -> Void)
        case someOtherCommand
    }
    
    struct State: StateType {
        var dataSource: TableViewControllerDataSource
        var text: String = ""
    }
    
    var store: Store<Action, State, Command>!
    
    lazy var reducer:(Action, State) -> (state: State, command: Command?) = { [weak self] (action: Action, state: State) in
     
        var state = state
        var command: Command? = nil

        switch action {
        case .updateText(let text):
            state.text = text
        case .addTodos(let items):
            state.dataSource = TableViewControllerDataSource(todos: items + state.dataSource.todos, owner: state.dataSource.owner)
        case .removeTodo(let index):
            if index > state.dataSource.todos.count - 1 {
                print("out of bounds")
                break
            }
            let newTodos = Array(state.dataSource.todos[0..<index] + state.dataSource.todos[(index + 1)..<state.dataSource.todos.count])
            state.dataSource = TableViewControllerDataSource(todos: newTodos, owner: state.dataSource.owner)
        case .loadToDos:
            command = Command.loadToDos { (self?.store.dispatch(action: .addTodos(items: $0)))  }
        }
        return (state, command)
    }
    
    func stateDidChanged(state:State, previousState: State?, command: Command?) {
        if let command = command {
            switch command {
            case .loadToDos(let handler):
                ToDoStore.shared.getToDoItems(completionHandler: handler)
            case .someOtherCommand:
                // Placeholder command.
                break
            }
        }

        if previousState == nil || previousState!.dataSource.todos != state.dataSource.todos {
            let dataSource = state.dataSource
            tableView.dataSource = dataSource
            tableView.reloadData()
            title = "TODO - (\(dataSource.todos.count))"
        }
        
        if previousState == nil  || state.text != previousState!.text {
            let isItemLengthEnough = state.text.characters.count >= 3
            navigationItem.rightBarButtonItem?.isEnabled = isItemLengthEnough
            
            let inputIndexPath = IndexPath(row: 0, section: TableViewControllerDataSource.Section.input.rawValue)
            guard let inputCell = tableView.cellForRow(at: inputIndexPath) as? LRTableViewCell else { return }
            
            inputCell.textFiled.text = state.text
        }
        
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
        let dataSource = TableViewControllerDataSource(todos: [], owner: self)
        store = Store(reducer: reducer, initialState: State(dataSource: dataSource, text: ""))
        store.subscribe { [weak self] state, previousState, command in
            self?.stateDidChanged(state: state, previousState: previousState, command: command)
        }
        stateDidChanged(state: store.state, previousState: nil, command: nil)
        store.dispatch(action: .loadToDos)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            self.dismiss(animated: true, completion: nil)
        }
    }

  
    @IBAction func addButtonPressed(_ sender: Any) {
        store.dispatch(action: .addTodos(items: [store.state.text]))
    }
    
}

// MARK: - Table view data source
extension LRTableViewController {
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard indexPath.section == TableViewControllerDataSource.Section.todos.rawValue else {
            return
        }
        store.dispatch(action: .removeTodo(index: indexPath.row))
    }
    
}

extension LRTableViewController : TableViewInputCellDelegate {
    func inputChanged(cell: LRTableViewCell, text: String) {
        store.dispatch(action: .updateText(text: text))

    }
}
